/**
 * Copyright 2020 Huawei Technologies Co., Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "kernel_info.h"

#include "config/ops_json_file.h"
#include "graph/debug/ge_attr_define.h"
#include "graph/utils/tensor_utils.h"
#include "util/log.h"
#include "util/util.h"

using namespace std;
using namespace ge;
using namespace ::aicpu::FWKAdapter;

namespace aicpu {
Status KernelInfo::Initialize(const map<string, string> &options) {
  AICPU_CHECK_RES(Finalize());
  // read kernel info json file
  if (!ReadOpInfoFromJsonFile()) {
    AICPU_REPORT_CALL_ERROR(
        "Call ReadOpInfoFromJsonFile to read kernel info from json file failed.");
    return LOAD_CONFIG_JSON_FILE_FAILED;
  }
  AICPU_IF_BOOL_EXEC(
      ((op_info_json_file_.find(kKernelConfigOpInfos) == op_info_json_file_.end()) ||
       (op_info_json_file_.find(kKernelConfigLibName) == op_info_json_file_.end())),
      AICPUE_LOGW("Json file does not have op_infos or lib_name.") return SUCCESS)
  try {
    OpInfoDescs info_desc = op_info_json_file_;
    AICPUE_LOGI("Read json file, op size is: %lu.", info_desc.opInfos.size());
    return FillOpInfos(info_desc);
  } catch (const nlohmann::json::exception &e) {
    AICPU_REPORT_INNER_ERROR("Parse json file[%s] failed, %s.",
        op_info_json_file_.dump().c_str(), e.what());
    return LOAD_CONFIG_JSON_FILE_FAILED;
  }
}

ge::Status KernelInfo::Finalize() {
  infos_.clear();
  return SUCCESS;
}

Status KernelInfo::FillOpInfos(OpInfoDescs &info_desc) {
  for (const auto &op_desc : info_desc.opInfos) {
    AICPU_IF_BOOL_EXEC(op_desc.opName.empty(), continue)

    auto ret = infos_.emplace(
        pair<string, aicpu::OpFullInfo>(op_desc.opName, op_desc.opInfo));
    if (!ret.second) {
      AICPUE_LOGW("Insert a pair of op[%s] and OpInfo failed.",
                  op_desc.opName.c_str());
    }
    AICPUE_LOGD("Read json file, op_name: %s.", op_desc.opName.c_str());
  }
  return SUCCESS;
}

const string KernelInfo::GetOpsPath(const void *instance) const {
  char resoved_path[PATH_MAX] = {0x00};
  string real_file_path;
  string path_base = GetSoPath(instance) + "../../../..";
  AICPU_IF_BOOL_EXEC(realpath(path_base.c_str(), resoved_path) == nullptr,
      AICPU_REPORT_INNER_ERROR("realpath [%s] failed, %s.",
          path_base.c_str(), strerror(errno));
      return real_file_path);
  real_file_path = resoved_path;
  return real_file_path;
}

Status KernelInfo::GetOpInfos(map<string, aicpu::OpFullInfo> &op_infos) const {
  op_infos = infos_;
  return SUCCESS;
}

Status KernelInfo::GetOpInfo(string &op_type, OpFullInfo &op_info) const {
  auto iter = infos_.find(op_type);
  if (iter != infos_.end()) {
    op_info = iter->second;
    return SUCCESS;
  }
  return OP_NOT_EXIST_IN_KERNEL_LIBS;
}
}  // namespace aicpu